﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Utility.BehaviourTree
{
	public abstract class CheckNode : LeafNode
	{
		protected override Status OnUpdate ()
		{
			if (OnPreUpdate ())
			{
				return Check (DataBoard) ? Status.Success : Status.Failure;
			}
			return Status.Error;
		}

		protected override bool OnPreUpdate () { return true; }
		protected abstract bool Check (DataBoard databoard);
	}

	public abstract class CheckDataboardNode : CheckNode
	{
		protected string key;
		public CheckDataboardNode (string key)
		{
			this.key = key;
		}

		protected override bool OnPreUpdate ()
		{
			if (string.IsNullOrEmpty (key))
			{
				Error ("Key is null or empty");
				return false;
			}
			return true;
		}
	}

	#region check condition
	[HideFromCreateMenu]
	public class CheckConditionNode : CheckNode
	{
		Func<DataBoard, bool> condition;

		public CheckConditionNode (Func<DataBoard, bool> condition)
		{
			this.condition = condition;
		}

		protected override bool OnPreUpdate ()
		{
			if (condition == null)
			{
				Error ("Condition is null");
				return false;
			}
			return true;
		}

		protected override bool Check (DataBoard databoard)
		{
			return condition (DataBoard);
		}
	}
	#endregion
	#region check not null
	[HideFromCreateMenu]
	public class CheckNotNullNode<T> : CheckDataboardNode
		where T : class
	{
		public CheckNotNullNode (string key) : base (key)
		{
		}

		protected override bool Check (DataBoard databoard)
		{
			T value;
			if (databoard.TryGet (key, out value))
			{
				return value != null;
			}
			return false;
		}
	}

	[HideFromCreateMenu]
	public class CheckNotNullNode : CheckNotNullNode<object>
	{
		public CheckNotNullNode (string key) : base (key)
		{
		}
	}
	#endregion
	#region check number
	public enum CheckType
	{
		Equal,
		Greater,
		GreaterEqual,
		Less,
		LessEqual
	}
	[HideFromCreateMenu]
	public class CheckIntNode : CheckDataboardNode
	{
		int value;
		CheckType type;

		public CheckIntNode (string key, int value, CheckType type) : base (key)
		{
			this.value = value;
			this.type = type;
		}

		protected override bool Check (DataBoard databoard)
		{
			int data = databoard.TryGet (key, out data) ? data : 0;
			switch (type)
			{
				case CheckType.Equal:
					return data == value;
				case CheckType.Greater:
					return data > value;
				case CheckType.GreaterEqual:
					return data >= value;
				case CheckType.Less:
					return data < value;
				case CheckType.LessEqual:
					return data <= value;
			}
			return false;
		}
	}
	[HideFromCreateMenu]
	public class CheckFloatNode : CheckDataboardNode
	{
		float value;
		CheckType type;

		public CheckFloatNode (string key, float value, CheckType type) : base (key)
		{
			this.value = value;
			this.type = type;
		}

		protected override bool Check (DataBoard databoard)
		{
			float data = databoard.TryGet (key, out data) ? data : 0;
			switch (type)
			{
				case CheckType.Equal:
					return data == value;
				case CheckType.Greater:
					return data > value;
				case CheckType.GreaterEqual:
					return data >= value;
				case CheckType.Less:
					return data < value;
				case CheckType.LessEqual:
					return data <= value;
			}
			return false;
		}
	}
	#endregion
	#region check bool
	[HideFromCreateMenu]
	public class CheckBoolNode : CheckDataboardNode
	{
		bool value;

		public CheckBoolNode (string key, bool value) : base (key)
		{
			this.value = value;
		}

		protected override bool Check (DataBoard databoard)
		{
			bool data = databoard.TryGet (key, out data) ? data : false;
			return data == value;
		}
	}
	#endregion
}